package droid.frame.utils.http;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Message;
import android.widget.ImageView;

import java.util.Map;
import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import droid.frame.Config;
import droid.frame.activity.HandlerMgr;
import droid.frame.utils.android.Log;
import droid.frame.utils.lang.FileUtils;
import droid.frame.utils.net.NetReceiver;

/**
 * @author coffee
 *         <p>
 *         2013年12月17日下午2:40:24
 */
@SuppressLint("UseSparseArrays")
public class HttpLoader {

    public final static int STATE_FAILED = -1;
    public final static int STATE_PREPARE = 0; // 初始状态
    public final static int STATE_START = 1;
    public final static int STATE_SUCCESS = 2;

    // 加载文本
    public final static int TYPE_TEXT = 0;
    // 资源类型图片
    public final static int TYPE_IMAGE = 1;
    // 上传(图片|文件)
    public final static int TYPE_upload = 2;

    private static Vector<HttpReq> imageReq = new Vector<HttpReq>();

    private static Vector<HttpReq> textReq = new Vector<HttpReq>();

    private static Vector<HttpReq> uploadReq = new Vector<HttpReq>();

    private static HttpLoader instance;

    private ExecutorService executorService;

    private HttpLoader() {
        executorService = Executors.newCachedThreadPool();
    }

    public static HttpLoader getInstance() {
        if (instance == null) {
            instance = new HttpLoader();
        }
        return instance;
    }

    class TextRunnable implements Runnable {
        private HttpReq req;

        public TextRunnable(HttpReq req) {
            this.req = req;
        }

        @Override
        public void run() {
            req.setState(STATE_START);
            // 先从缓存中获取
            if (req.getParam(HttpParam.cache)) {
                String result = loadCacheJson(req.getMsgId());
                // 缓存不为空的时候在通知, 否则可能会导致业务失败。即提示用户获取数据失败
                if (result != null && result.trim().length() > 0) {
                    notifyMessage(req, result);
                }
            }
            Object objResult = null;
            if (req.getHttpRunnable() != null) {
                objResult = req.getHttpRunnable().run();
            }
            // 默认的数据加载方式
            else {
                Log.w("http:url_" + req.getMsgId(), req.getUrl() + "\n" + req.getParams(), null);
                if (req.getParams() != null && req.getParams().size() > 0) {
                    StringBuilder builder = new StringBuilder();
                    for (Map.Entry<String, Object> entry : req.getParams().entrySet()) {
                        builder.append(entry.getKey() + "=" + entry.getValue() + "&");
                    }
                    Log.e("http:url_" + req.getMsgId() + "详细参数路径", req.getUrl() + "?" + builder.toString(), null);
                }
                // 上传图片到服务器
                if (req.getParam(HttpParam.postImage)) {
                    // ??
                    // req.getParams().remove(HttpParam.postImage);
                    // objResult = new HttpClient().postWithImage(req.getUrl(), req.getParams());
                } else {
                    if (req.getParam(HttpParam.postText)) {
                        HttpClient client = new HttpClient();
                        // req.setHttpClient(client);
                        objResult = client.post(req.getUrl(), req.getParams());
                    } else {
                        String url = req.getUrl();
                        if (url.endsWith("?") == false) {
                            url = url + "?";
                        }
                        String linkUrl = url + HttpClient.getParamsString(req.getParams());
                        HttpClient client = new HttpClient();
                        // req.setHttpClient(client);
                        objResult = client.get(linkUrl);
                    }
                }
            }
            Log.i("http:url_" + req.getMsgId(), objResult);
            // 先移除请求,
            // 因为在notifyMessage的时候Activity#handleMessage中处理dialog以后。线程会卡主。
            boolean success = textReq.remove(req);
            if (success == false) {// 从缓存中删除失败
                Log.e("http:state", "HttpReq 删除失败 " + req, null);
                Log.d("http:state [all]", textReq);
                req.setState(STATE_FAILED);
            }
            // http请求超时
            if (Integer.valueOf(MsgID.http_time_out).equals(objResult)) {
                // 通知界面请求超时
                HandlerMgr.sendMessage(req.getMsgId(), MsgID.http_time_out, req.getMsgId());
            } else {
                String result = objResult + "";
                if (req.getParam(HttpParam.cache)) {
                    cacheJson(req.getMsgId(), result);
                }
                notifyMessage(req, result);
            }
            if (req.getHttpCallback() != null) {
                req.getHttpCallback().callback(objResult, req);
            }
        }
    }

    private void notifyMessage(HttpReq req, String result) {
        //
        Message msg = Message.obtain();
        msg.what = req.getMsgId();
        msg.obj = result;
        msg.arg1 = req.getArg1();
        msg.arg2 = req.getArg2();
        //
        // Looper.prepare();
        HandlerMgr.sendMessage(msg, 0);
    }

    public void sendReq(final HttpReq req) {
        if (req.getParam(HttpParam.toastNet) == false) {
            // 如果指定不需要提示的话,则跳过网络是否可用的检查
        } else {
            if (NetReceiver.isConnected() == false) {
                Message msg = Message.obtain();
                msg.what = MsgID.net_unavailable;
                msg.obj = "网络不可用";
                HandlerMgr.removeCallbacksAndMessages();
                HandlerMgr.sendMessage(msg, 1000);
                // 如果不需要从缓存中读取
                if (req.getParam(HttpParam.cache) == true) {
                    // continue 继续执行, 读取cache的内容
                } else {
                    return;
                }
            }
        }
        if (req.getType() == TYPE_IMAGE) {
            // 线程池中已经包含该网络请求
            if (imageReq.contains(req)) {
                return;
            } else {
                imageReq.add(req);
            }
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    //
                    Log.d("http:img", req.getUrl());
                    //
                    Bitmap bmp = BitmapUtils.loadBitmapFromNet(req.getUrl());
                    if (req.getHttpCallback() != null) {
                        req.getHttpCallback().callback(bmp, req);
                    }
                    imageReq.remove(req);
                }
            });
        }
        // 处理文件上传
        else if (req.getType() == TYPE_upload) {
            if (uploadReq.contains(req)) {
                return;
            } else {
                uploadReq.add(req);
            }
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    Log.d("http:upload", req.getUrl());
                    //
                    String[] arr = new String[req.getParams().size()];
                    int i = 0;
                    for (Object fileLocalPath : req.getParams().values()) {
                        if (fileLocalPath == null) {
                            continue;
                        }
                        arr[i] = String.valueOf(fileLocalPath);
                        i++;
                    }
                    // 上传
                    String result = HttpClient.postFiles(req.getUrl(), arr);
                    notifyMessage(req, result);
                    uploadReq.remove(req);
                }
            });
        } else {
            // 如果线程池中存在该请求
            boolean has = false;
            for (int i = 0; i < textReq.size(); i++) {
                if (textReq.get(i).getMsgId() == req.getMsgId() && req.getState() != STATE_FAILED && textReq.get(i).getArg1() == req.getArg1()) {
                    has = true;
                    break;
                }
            }
            // 该请求中线程池中已经存在
            if (has) {
                return;
            } else {
                textReq.add(0, req); // ////////////不同点，文本请求有优先级
            }
            executorService.execute(new TextRunnable(req));
        }
    }

    /**
     * 加载json缓存
     *
     * @param msgId
     * @return
     */
    public String loadCacheJson(int msgId) {
        String jsonFile = Config.getJsonDir() + "/" + msgId + ".json";
        Log.d("http:url_cache", jsonFile);
        String json = FileUtils.read(jsonFile);
        return json;
    }

    private void cacheJson(int msgId, String json) {
        if (json == null || json.trim().length() == 0) {
            return;
        }
        String jsonFile = Config.getJsonDir() + "/" + msgId + ".json";
        FileUtils.write(jsonFile, json);
    }

    /**
     * @param imgUrl
     * @param image
     * @param context
     */
    public void loadImage(final String imgUrl, final ImageView image, final Activity context) {
        Bitmap bmpCache = BitmapUtils.loadBitmapFromLocal(imgUrl);
        if (bmpCache != null) {
            image.setImageBitmap(bmpCache);
        } else {
            HttpLoader.getInstance().sendReq(new HttpReq(imgUrl, new HttpCallback() {
                @Override
                public void onSuccess(final Object result) {
                    context.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Bitmap loadedImage = (Bitmap) result;
                            BitmapUtils.cacheBitmapToFile(loadedImage, imgUrl);
                            image.setImageBitmap(loadedImage);
                        }
                    });
                }
            }));
        }
    }

}
